Android窗口管理分析(二)——WindowManagerService图层管理之窗口的添加

Android窗口管理分析(二)——WindowManagerService图层管理之窗口的添加

本文主要从以下几点分析:

  • 窗口的分类:Activity、Dialog、PopupWindow、Toast等对应窗口的区别
  • 窗口的添加和删除
  • 窗口的分组与窗口Z的顺序
  • Window、IWindow、WindowState、WindowToken、AppToken等之间的关系

Android窗口大概分为几种?

Android将窗口大致分为三类:

  1. 应用窗口(拥有自己的WindowToken) 例如:Activity与Dialog
  2. 子窗口(必须依附到其他非子窗口才能存在,比如Activity等) 例如:PopupWindow
  3. 系统窗口 例如:Toast

这里Dialog比较特殊,从表现上来说偏向于子窗口,必须依附到Activity才能存在,而从性质上来说,仍然是应用窗口,有自己的WindowToken。

窗口是怎么添加的?

以悬浮窗为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void addTextViewWindow(Context context){

TextView mview=new TextView(context);
...<!--设置颜色 样式-->
<!--关键点1-->
WindowManager mWindowManager = (WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
<!--关键点2-->
wmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.width = 800;
wmParams.height = 800;
<!--关键点3-->
mWindowManager.addView(mview, wmParams);
}

流程图

WindowToken是什么样的?

首先需要知道下面一些概念:

  • IWindow: APP端窗口暴露给WMS的抽象实例,同时也是WMS向APP端发送消息的Binder通道。
  • WindowState:WMS端窗口的令牌,与IWindow窗口一一对应,是WMS管理窗口的重要依据。
  • WindowToken:是窗口的令牌,也是窗口分组的依据,在WMS端,和分组对应的数据结构是WindowToken
  • AppToken:是ActivityRecord里面的IApplicationToken.Stub appToken代理。

Activity与Dialog对应的是AppWindowToken,PopupWindow对应的是普通的WindowToken。

Session和App进程对应关系是什么样的?

  1. Session与App进程一一对应,进一步为当前进程建立SurfaceSession会话。
  2. Session是App同WMS通信的通道,SurfaceSession是WMS为SurfaceFlinger申请的通信通道,SurfaceSession与APP也是一一对应的。
  3. SurfaceSession的SurfaceFlinger代理就是SurfaceComposerClient里的ISurfaceComposerClient mClient对象,它是SurfaceFlinger为每个APP封装的一个代理。

ISurfaceComposerClient是怎么一步步创建的?

利用ComposerService这样的单例对象为每个App在WMS申请一个ISurfaceComposerClient对象。在WMS端表现为BPSurfaceComposerClient,在SurfaceFlinger端表现为BnSurfaceComposerClient。

postSyncBarrier()有什么用?在ViewRootImpl的setView中的应用是什么样的?

这个挡板是用来阻塞同步消息的,在挡板撤销之前,只会执行异步消息。在ViewRootImpl的setView中,目的是保证在mTraversalRunnable的所有同步Message之前被执行,保证View绘制的最高优先级。

performTraversals函数主要作用是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void performTraversals() {
final View host = mView;
...
if (mFirst || windowShouldResize || insetsChanged ||
viewVisibilityChanged || params != null) {
<!--关键点1 申请Surface或者重新设置参数-->
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
<!--关键点2 测量-->
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
}
<!--关键点3 布局-->
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
<!--关键点4 更新window-->
try {
mWindowSession.setInsets(mWindow, insets.mTouchableInsets,
contentInsets, visibleInsets, touchableRegion);
...
<!--关键点5 绘制-->
performDraw();
...
}

relayout是如何向SurfaceFlinger申请Surface?

总结

Add View整体流程

  • APP去WMS登记窗口
  • APP新建Surface壳子,请求WMS填充Surface
  • WMS请求SurfaceFlinger分配窗口图层
  • SurfaceFlinger分配Layer,将结果回传给WMS
  • WMS将窗口信息填充到Surface传输到APP
  • APP端获得填充信息,获取与SurfaceFlinger通信的能力